package inc.veluvana.weatherforecaster

/**
 *
 * @author eduarc (Eduar Castrillo)
 */
class Order {
  
  /** items in this order */
  def items
  /** Total purchase price for this Order */
  def purchasePrice
  /** Total delivery time for this Order */
  def deliveryTime
  /** 
   * Status flag for this Order.
   * true if this Order has been modified through setAmount() and remove() methods
   * 
   * @see setAmount(Hardwood, int)
   * @see remove(Hardwood)
   */
  def modified
  
  /* Create a new instance of Order*/
  Order() {
    
    modified = false
    purchasePrice = 0
    deliveryTime  = 0
    items = [:]
  }
  
  /**
   * Add a hardwood to the order and the amount
   */
  void setAmount(hardwood, amount) {
      // Avoid add null hardwoods
    if (!hardwood) {
      throw new IllegalArgumentException("null hardwood")
    }
      // Amount cannot be negative
    if (amount < 0) {
      throw new IllegalArgumentException("Negative hardwood amount: ${amount}")
    }
      // check if the amount if modified
    def oldAmount = items[hardwood]
    if (!oldAmount || oldAmount != amount) {
      modified = true
      items[hardwood] = amount
    }
  }
  
  /**
   * Remove an item from this Order
   */
  void remove(hardwood) {
    items.remove(hardwood)
    modified = true
  }
  
  /**
   * Return the amount for the specified hardwood in this Order
   */
  def getAmount(hardwood) {
    items[hardwood]
  }
  
  /**
   * Return the purchase price for this order
   * 
   * @throw Exception if the purchase price need to be calculated
   * @return the purchase price of this Order
   */ 
  def getPurchasePrice() {
      // old state is found
    if (modified) calculateOrder()
    purchasePrice
  }
  
  /**
   * Return the purchase price for this order
   * @return the purchase price of this Order
   */ 
  def getDeliveryTime() {
      // old state is found
    if (modified) calculateOrder()
    deliveryTime
  }
  
  /**
   * Set and update the purchase price and delivery time of this order
   */
  void calculateOrder() {
      // let modify purchasePrice and deliveryTime
    modified = false
    
    deliveryTime = 0.0
    purchasePrice = 0.0
    
    items.each { hardwood, amount ->
        // add purchase price for woodtype i
      purchasePrice += amount * hardwood.unitPrice
      
        // Calculate the shipping time for hardwood type i
      def delTime = hardwood.deliveryTime
      def time = 0.0
      
           if (amount <= 100) time = 1   * delTime
      else if (amount <= 200) time = 2   * delTime
      else if (amount <= 300) time = 3   * delTime
      else if (amount <= 400) time = 4   * delTime
      else if (amount <= 500) time = 5   * delTime
      else                    time = 5.5 * delTime
      deliveryTime = Math.max(time, deliveryTime)
    }
  }
}

